package org.openinsula.vulcano.orm.command;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Test;
import org.openinsula.vulcano.core.command.invoker.CommandInvoker;
import org.openinsula.vulcano.orm.dao.Dao;
import org.openinsula.vulcano.orm.dao.query.DaoQuery;
import org.openinsula.vulcano.orm.dao.query.ProjectionDaoQuery;
import org.openinsula.vulcano.orm.dao.query.SimpleDaoQuery;
import org.openinsula.vulcano.orm.dao.query.projection.MaxProjection;
import org.openinsula.vulcano.orm.dao.query.spec.AndSpec;
import org.openinsula.vulcano.orm.dao.query.spec.EqualsSpec;
import org.openinsula.vulcano.orm.entity.Person;
import org.openinsula.vulcano.orm.entity.Pet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

@ContextConfiguration
public class CommandTemplateTestCase extends AbstractTransactionalJUnit4SpringContextTests {

	@Autowired
	private CommandInvoker commandInvoker;

	@Autowired
	private Dao dao;

	@Test
	public void testFind() {
		populateDatabase();
		
		CommandTemplate commandTemplate = new CommandTemplate(commandInvoker);

		DaoQuery<Person> personDaoQuery = new SimpleDaoQuery<Person>(Person.class, new AndSpec(new EqualsSpec("name", "Obi Wan"),
				new EqualsSpec("age", 25)));

		List<Person> result = commandTemplate.find(personDaoQuery);

		assertEquals(1, result.size());

		DaoQuery<Pet> petDaoQuery = new SimpleDaoQuery<Pet>(Pet.class, new EqualsSpec("person", result.get(0)));

		assertEquals(2, commandTemplate.find(petDaoQuery).size());
		
		DaoQuery<Integer> ageDaoQuery = new ProjectionDaoQuery<Integer>(Person.class, new MaxProjection("age"));
		
		assertEquals(25, commandTemplate.findUnique(ageDaoQuery).intValue());
	}

	@Test(expected = IllegalStateException.class)
	public void testFindUnique() {
		populateDatabase();
		
		CommandTemplate commandTemplate = new CommandTemplate(commandInvoker);

		DaoQuery<Pet> daoQuery = new SimpleDaoQuery<Pet>(Pet.class);

		commandTemplate.findUnique(daoQuery);
	}
	
	@Test
	public void testDelete() {
		populateDatabase();

		CommandTemplate commandTemplate = new CommandTemplate(commandInvoker);

		DaoQuery<Pet> petDaoQuery = new SimpleDaoQuery<Pet>(Pet.class);

		List<Pet> result = commandTemplate.find(petDaoQuery);

		commandTemplate.remove(result.get(0), result.get(1));
		dao.flush();

		assertEquals(0, countRowsInTable("Pet"));
	}

	@Test
	public void testPersist() {
		populateDatabase();

		assertEquals(1, countRowsInTable("Person"));
		assertEquals(2, countRowsInTable("Pet"));
	}

	private void populateDatabase() {
		Person person = new Person();
		person.setName("Obi Wan");
		person.setAge(25);
		person.setJedi(true);

		Pet dog = new Pet();
		dog.setName("Woofy");
		dog.setPerson(person);

		Pet cat = new Pet();
		cat.setPerson(person);
		cat.setName("Simm");

		CommandTemplate commandTemplate = new CommandTemplate(commandInvoker);

		commandTemplate.persist(person, dog, cat);
	}

}
